﻿using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace zijian666.Data;

/// <summary>
/// 控制日志输出
/// </summary>
public static class Diagnostic
{
    private static readonly ConcurrentDictionary<object, IDisposable> SUBSCRIBES = new();

    public static void Subscribe(IObserver<DiagnosticListener> observer)
    {
        SUBSCRIBES.AddOrUpdate(observer, o => DiagnosticListener.AllListeners.Subscribe(observer), (_, o) => o);
    }

    public static void Unsubscribe(IObserver<DiagnosticListener> observer)
    {
        if (SUBSCRIBES.TryRemove(observer, out var subscribe))
        {
            subscribe.Dispose();
        }
    }


    private static readonly DiagnosticListener LISTENER = new(typeof(Diagnostic).Assembly.GetName().Name!);

    /// <summary>
    /// 是否启用日志
    /// </summary>
    public static bool IsEnabled => LISTENER.IsEnabled() || IsDebug;

    /// <summary>
    /// 是否启用调试模式(在日志禁用时将日志输出到控制台)
    /// </summary>
    public static bool IsDebug { get; set; } = Debugger.IsAttached;

    /// <summary>
    /// 写日志
    /// </summary>
    public static void Wirte(string name
        , Func<string> getContent
        , [CallerFilePath] string file = null!
        , [CallerMemberName] string member = null!
        , [CallerLineNumber] int line = 0)
    {
        if (!LISTENER.IsEnabled())
        {
            if (IsDebug)
            {
                Console.WriteLine(LISTENER.Name + " => " + new DiagnosticData(name, getContent(), null, file, member, line));
            }
            return;
        }
        LISTENER.Write(name, new DiagnosticData(name, getContent(), null, file, member, line));
    }


    /// <summary>
    /// 写日志
    /// </summary>
    public static void Wirte(string name
        , string content
        , [CallerFilePath] string file = null!
        , [CallerMemberName] string member = null!
        , [CallerLineNumber] int line = 0)
    {
        if (!LISTENER.IsEnabled())
        {
            if (IsDebug)
            {
                Console.WriteLine(LISTENER.Name + " => " + new DiagnosticData(name, content, null, file, member, line));
            }
            return;
        }
        LISTENER.Write(name, new DiagnosticData(name, content, null, file, member, line));
    }

    /// <summary>
    /// 写日志
    /// </summary>
    public static void Error(Exception exception
        , [CallerFilePath] string file = null!
        , [CallerMemberName] string member = null!
        , [CallerLineNumber] int line = 0)
    {
        if (!LISTENER.IsEnabled())
        {
            if (IsDebug)
            {
                Console.WriteLine(LISTENER.Name + " => " + new DiagnosticData(member, exception.Message, exception, file, member, line));
            }
            return;
        }
        LISTENER.Write("Error", new DiagnosticData(member, exception.Message, exception, file, member, line));
    }
}
